package gateway.utils;


import com.alibaba.fastjson2.JSONObject;
import com.yymt.comp.gateway.entity.RouteInstance;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import static java.util.Collections.list;
import static org.apache.commons.io.IOUtils.toByteArray;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.springframework.http.HttpMethod.valueOf;

@Slf4j
public class HttpRequestMapper {

  public RequestEntity<byte[]> map(HttpServletRequest request, RouteInstance instance) throws IOException {
    byte[] body = extractBody(request);
    HttpHeaders headers = extractHeaders(request);
    HttpMethod method = extractMethod(request);
    URI uri = extractUri(request, instance);
    return new RequestEntity<>(body, headers, method, uri);
  }

  private URI extractUri(HttpServletRequest request, RouteInstance instance) throws UnsupportedEncodingException {
    //如果content path 不为空，移除content path
    String requestURI = StringUtils.isEmpty(request.getContextPath()) ? request.getRequestURI() :
        StringUtils.substringAfter(request.getRequestURI(), request.getContextPath());

    //处理中文被自动编码问题
    String query = request.getQueryString() == null ? EMPTY : URLDecoder.decode(request.getQueryString(), "utf-8");

    // 需要重写path
    if (instance.isRewrite()) {
      // 截取通配符前面的网关前缀
      String prefix = StringUtils.substringBefore(instance.getPath(), "/**");
      // 截取掉网关前缀
      requestURI = StringUtils.substringAfter(requestURI, prefix);
    }
    URI redirectURL = UriComponentsBuilder.fromUriString(instance.getUri() + requestURI).query(query).build().encode().toUri();
    log.info("real request url: {}", redirectURL.toString());
    return redirectURL;
  }

  private HttpMethod extractMethod(HttpServletRequest request) {
    return valueOf(request.getMethod());
  }

  private HttpHeaders extractHeaders(HttpServletRequest request) {
    HttpHeaders headers = new HttpHeaders();
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
      String name = headerNames.nextElement();
      List<String> value = Collections.list(request.getHeaders(name));
      headers.put(name, value);
    }
    String userHeaderKey = "userInfo";
    Object userInfo = request.getAttribute(userHeaderKey);
    if (userInfo != null){
      String jsonString = JSONObject.toJSONString(userInfo);
      List<String> list = new ArrayList<>();
      list.add(jsonString);
      headers.put(userHeaderKey,list);
    }
    return headers;
  }

  private byte[] extractBody(HttpServletRequest request) throws IOException {
    return toByteArray(request.getInputStream());
  }
}
